import java.io.*;
import antlr.CommonAST;
import antlr.collections.AST;
import antlr.debug.misc.ASTFrame;
import antlr.DumpASTVisitor;
import antlr.RecognitionException;
import antlr.TokenStreamException;

class sim2d {
	Display display = null;
	boolean graphical_ast = false;
	boolean text_ast = false;
	boolean skip_simulation = false; 
	boolean dump_symbol_table = false;
	boolean suppress_display = false;
	int iteration_delay = 250;
	int quit_count = -1;
	String src_file = "";

	private static void dumpAST(AST node, int level) {
		if (node != null) {
			for (int i = 0; i < level; i++)
				System.out.print("   ");
			System.out.println(
					node.getText());
			dumpAST(node.getFirstChild(), level+1);
			dumpAST(node.getNextSibling(), level);
		}
	}
	public static void main(String[] args) {
		sim2d newsim = new sim2d(args);
	}
	public sim2d(String args[]) {
		for (int i = 0; i < args.length; i++) {
			if (args[i].equals("-g")) {
				graphical_ast = true;
			} else if (args[i].equals("-t")) {
				text_ast = true;
			} else if (args[i].equals("-s")) {
				suppress_display = true;
			} else if (args[i].equals("-v")) {
				log.on();
			} else if (args[i].equals("-r")) {
				iteration_delay = new Integer(args[++i]);
			} else if (args[i].equals("-i")) {
				quit_count = new Integer(args[++i]);
			} else if (args[i].equals("-d")) {
				dump_symbol_table = true;
			} else if ((args[i].equals("-h"))
			        || (args[i].equals("--help"))
			        || (args[i].equals("-help"))) {
				System.out.println("Sim2d options:\n"
						+ "   -h            This message\n"
						+ "   -s            Suppress map display\n"
						+ "   -i [number]   Quit after [number] iterations\n"
						+ "   -r [delay]    Time delay between iterations in msecs\n"
						+ "   -g            Show graphical AST\n"
						+ "   -t            Show textual AST\n"
						+ "   -d            Dump symbol table after each iteration\n"
						+ "   -v            Output verbose debugging text\n");
				System.exit(0);
			} else {
				src_file = args[i];
			}
		}

		try {
			FileInputStream filename = new FileInputStream(src_file);
			DataInputStream input = new DataInputStream(filename);
			sim2dLexer lexer = new sim2dLexer(new DataInputStream(input));
			lexer.setFilename(src_file);
			sim2dParser parser = new sim2dParser(lexer);
			parser.setFilename(src_file);
			// Parse the input expression
			parser.file();
			CommonAST t = (CommonAST)parser.getAST();
			// Print the resulting tree out in LISP notation
			if (text_ast) {
            // Print the AST in a human-readable format
		   	System.out.println(t.toStringList());
			}
			if (graphical_ast) {
            // Open a window in which the AST is displayed graphically
            ASTFrame frame = new ASTFrame("AST from the Sim2d parser", t);
            frame.setVisible(true);
			}

			sim2dWalker walker = new sim2dWalker();
			// Traverse the tree created by the parser
			Sim2dInterpreter interp = Sim2dInterpreter.getInstance();
			interp.setWalker(walker);
			walker.file(t);
			if (dump_symbol_table) {
				interp.sym.Dump();
			}
			int iter = 0;
			if (!suppress_display) {
	   		display = new Display(interp.sym);
			}
			while (iter != quit_count) {
				for (Sim2dDataType symbol : interp.sym) {
					if (symbol instanceof Sim2dObject) {
						try {
	  					    Thread.currentThread().sleep(iteration_delay);
						} catch (InterruptedException e) {
						}
						log.out("Running rule " + symbol.getName());
						interp.runRule((Sim2dObject)symbol);
						Sim2dObject objsymbol = (Sim2dObject)symbol;
						Sim2dFloat x = (Sim2dFloat)objsymbol.getField("x");
						Sim2dFloat y = (Sim2dFloat)objsymbol.getField("y");
						Sim2dFloat heading = (Sim2dFloat)objsymbol.getField("heading");
						Sim2dFloat speed = (Sim2dFloat)objsymbol.getField("speed");
						x.var += speed.var * Math.sin(Math.toRadians(heading.var));
						y.var -= speed.var * Math.cos(Math.toRadians(heading.var));

							
					}

				}
				if (dump_symbol_table) {
	   		   interp.sym.Dump();
				}
				if (!suppress_display) {
			   	display.refresh();
				}
				if (quit_count > 0) {
					iter++;
				}
			}
			System.exit(0);
		} catch (FileNotFoundException e) {
			System.err.println("Error (file): "+e.getMessage());
			System.exit(-1);
		}
		catch(TokenStreamException e) {
			System.err.println("Error (token): "+e.getMessage());
		}
		catch(RecognitionException e) {
			System.err.println("Error (recog): "+e.getMessage());
		}
		catch(Exception e) {
			System.err.println("Error (excep): " +e);
			e.printStackTrace();
		}
	}
}
